home *** CD-ROM | disk | FTP | other *** search
- /* clip.c */
-
- /*
- * Mesa 3-D graphics library
- * Version: 1.2
- * Copyright (C) 1995 Brian Paul (brianp@ssec.wisc.edu)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- * Functions for clipping points, lines, and polygons against the view
- * volume and user-defined clipping planes.
- */
-
-
- /*
- $Id: clip.c,v 1.14 1995/10/14 17:41:29 brianp Exp $
-
- $Log: clip.c,v $
- * Revision 1.14 1995/10/14 17:41:29 brianp
- * made glClipPlane display list-able
- *
- * Revision 1.13 1995/09/15 18:54:09 brianp
- * changed INSIDE, OUTSIDE macros to fix Oleg Krivosheev's clipping problems
- *
- * Revision 1.12 1995/07/28 21:32:12 brianp
- * fixed aux data interpolation bug in gl_viewclip_line()
- *
- * Revision 1.11 1995/07/24 20:34:16 brianp
- * replaced memset() with MEMSET() and memcpy() with MEMCPY()
- *
- * Revision 1.10 1995/07/14 16:11:26 brianp
- * tests for divide by zero added to gl_userclip_line()
- *
- * Revision 1.9 1995/06/02 13:59:16 brianp
- * changed MAX_VERTICES to VB_SIZE
- *
- * Revision 1.8 1995/05/22 21:02:41 brianp
- * Release 1.2
- *
- * Revision 1.7 1995/05/12 19:24:13 brianp
- * replaced CC.Mode!=0 with INSIDE_BEGIN_END
- *
- * Revision 1.6 1995/03/24 15:30:41 brianp
- * introduced VB
- *
- * Revision 1.5 1995/03/09 21:41:03 brianp
- * new ModelViewInv matrix logic
- *
- * Revision 1.4 1995/03/09 20:07:46 brianp
- * changed order of arguments in gl_transform_vector
- *
- * Revision 1.3 1995/03/08 19:01:11 brianp
- * removed extra #include "clip.h"
- *
- * Revision 1.2 1995/03/04 19:29:44 brianp
- * 1.1 beta revision
- *
- * Revision 1.1 1995/02/24 14:18:09 brianp
- * Initial revision
- *
- */
-
-
- #include <string.h>
- #include "GL/gl.h"
- #include "clip.h"
- #include "context.h"
- #include "list.h"
- #include "macros.h"
- #include "vb.h"
- #include "xform.h"
-
-
-
-
- /* Linear interpolation between A and B: */
- #define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
-
-
- #define EYE_SPACE 1
- #define CLIP_SPACE 2
-
- static GLuint Space;
-
-
-
- /*
- * This function is used to interpolate colors, indexes, and texture
- * coordinates when clipping has to be done. In general, we compute
- * aux[dst] = aux[in] + t * (aux[out] - aux[in])
- * where aux is the quantity to be interpolated.
- * Input: dst - index of array position to store interpolated value
- * t - a value in [0,1]
- * in - index of array position corresponding to 'inside' vertex
- * out - index of array position corresponding to 'outside' vertex
- */
- static void interpolate_aux( GLuint dst, GLfloat t, GLuint in, GLuint out )
- {
- if (CC.ClipMask & CLIP_FCOLOR_BIT) {
- VB.Fcolor[dst][0] = LINTERP( t, VB.Fcolor[in][0], VB.Fcolor[out][0] );
- VB.Fcolor[dst][1] = LINTERP( t, VB.Fcolor[in][1], VB.Fcolor[out][1] );
- VB.Fcolor[dst][2] = LINTERP( t, VB.Fcolor[in][2], VB.Fcolor[out][2] );
- VB.Fcolor[dst][3] = LINTERP( t, VB.Fcolor[in][3], VB.Fcolor[out][3] );
- }
- else if (CC.ClipMask & CLIP_FINDEX_BIT) {
- VB.Findex[dst] = LINTERP( t, VB.Findex[in], VB.Findex[out] );
- }
-
- if (CC.ClipMask & CLIP_BCOLOR_BIT) {
- VB.Bcolor[dst][0] = LINTERP( t, VB.Bcolor[in][0], VB.Bcolor[out][0] );
- VB.Bcolor[dst][1] = LINTERP( t, VB.Bcolor[in][1], VB.Bcolor[out][1] );
- VB.Bcolor[dst][2] = LINTERP( t, VB.Bcolor[in][2], VB.Bcolor[out][2] );
- VB.Bcolor[dst][3] = LINTERP( t, VB.Bcolor[in][3], VB.Bcolor[out][3] );
- }
- else if (CC.ClipMask & CLIP_BINDEX_BIT) {
- VB.Bindex[dst] = LINTERP( t, VB.Bindex[in], VB.Bindex[out] );
- }
-
- if (CC.ClipMask & CLIP_TEXTURE_BIT) {
- /* TODO: is more sophisticated texture coord interpolation needed?? */
- if (Space==CLIP_SPACE) {
- /* also interpolate eye Z component */
- VB.Eye[dst][2] = LINTERP( t, VB.Eye[in][2], VB.Eye[out][2] );
- }
- VB.TexCoord[dst][0] = LINTERP(t,VB.TexCoord[in][0],VB.TexCoord[out][0]);
- VB.TexCoord[dst][1] = LINTERP(t,VB.TexCoord[in][1],VB.TexCoord[out][1]);
- }
-
- }
-
-
-
-
- void gl_clipplane( GLenum plane, const float *equation )
- {
- GLint p;
-
- p = (GLint) (plane - GL_CLIP_PLANE0);
- if (p<0 || p>=MAX_CLIP_PLANES) {
- gl_error( GL_INVALID_ENUM, "glClipPlane" );
- return;
- }
-
- /*
- * The Equation is transformed by the transpose of the inverse of the
- * current modelview matrix and stored in the resulting eye coordinates.
- */
- if (!CC.ModelViewInvValid) {
- gl_compute_modelview_inverse();
- }
- gl_transform_vector( CC.Transform.ClipEquation[p], equation,
- CC.ModelViewInv );
- }
-
-
-
- void glClipPlane( GLenum plane, const GLdouble *equation )
- {
- GLfloat fequation[4];
- fequation[0] = (GLfloat) equation[0];
- fequation[1] = (GLfloat) equation[1];
- fequation[2] = (GLfloat) equation[2];
- fequation[3] = (GLfloat) equation[3];
- if (CC.CompileFlag) {
- gl_save_clipplane( plane, fequation );
- }
- if (CC.ExecuteFlag) {
- gl_clipplane( plane, fequation );
- }
- }
-
-
-
- void glGetClipPlane( GLenum plane, GLdouble *equation )
- {
- GLint p;
-
- if (INSIDE_BEGIN_END) {
- gl_error( GL_INVALID_OPERATION, "glGetClipPlane" );
- return;
- }
-
- p = (GLint) (plane - GL_CLIP_PLANE0);
- if (p<0 || p>=MAX_CLIP_PLANES) {
- gl_error( GL_INVALID_ENUM, "glGetClipPlane" );
- return;
- }
-
- equation[0] = (GLdouble) CC.Transform.ClipEquation[p][0];
- equation[1] = (GLdouble) CC.Transform.ClipEquation[p][1];
- equation[2] = (GLdouble) CC.Transform.ClipEquation[p][2];
- equation[3] = (GLdouble) CC.Transform.ClipEquation[p][3];
- }
-
-
-
-
- /**********************************************************************/
- /* View volume clipping. */
- /**********************************************************************/
-
-
- /*
- * Clip a point against the view volume.
- * Input: v - vertex-vector describing the point to clip
- * Return: 0 = outside view volume
- * 1 = inside view volume
- */
- GLuint gl_viewclip_point( const GLfloat v[] )
- {
- if ( v[0] > v[3] || v[0] < -v[3]
- || v[1] > v[3] || v[1] < -v[3]
- || v[2] > v[3] || v[2] < -v[3] ) {
- return 0;
- }
- else {
- return 1;
- }
- }
-
-
-
-
- /*
- * Clip a line segment against the view volume defined by -w<=x,y,z<=w.
- * Input: i, j - indexes into VB.V* of endpoints of the line
- * Return: 0 = line completely outside of view
- * 1 = line is inside view.
- */
- GLuint gl_viewclip_line( GLuint *i, GLuint *j )
- {
- GLfloat t, dx, dy, dz, dw;
- register GLuint ii, jj;
-
- Space = CLIP_SPACE;
- ii = *i;
- jj = *j;
-
- /*
- * We use 6 instances of this code to clip agains the 6 planes.
- * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
- * macros apprpriately.
- */
- #define GENERAL_CLIP \
- if (OUTSIDE(ii)) { \
- if (OUTSIDE(jj)) { \
- /* both verts are outside ==> return 0 */ \
- return 0; \
- } \
- else { \
- /* ii is outside, jj is inside ==> clip */ \
- /* new vertex put in position VB.Free */ \
- COMPUTE_INTERSECTION( VB.Free, jj, ii ) \
- if (CC.ClipMask) interpolate_aux( VB.Free, t, jj, ii ); \
- ii = VB.Free; \
- VB.Free++; \
- if (VB.Free==VB_SIZE) VB.Free = 1; \
- } \
- } \
- else { \
- if (OUTSIDE(jj)) { \
- /* ii is inside, jj is outside ==> clip */ \
- /* new vertex put in position VB.Free */ \
- COMPUTE_INTERSECTION( VB.Free, ii, jj ); \
- if (CC.ClipMask) interpolate_aux( VB.Free, t, ii, jj ); \
- jj = VB.Free; \
- VB.Free++; \
- if (VB.Free==VB_SIZE) VB.Free = 1; \
- } \
- /* else both verts are inside ==> do nothing */ \
- }
-
-
- #define X(I) VB.Clip[I][0]
- #define Y(I) VB.Clip[I][1]
- #define Z(I) VB.Clip[I][2]
- #define W(I) VB.Clip[I][3]
-
- /*
- * Begin clipping
- */
-
- /*** Clip against +X side ***/
- #define OUTSIDE(K) (X(K) > W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dx = X(out) - X(in); \
- dw = W(out) - W(in); \
- t = (X(in) - W(in)) / (dw-dx); \
- X(new) = X(in) + t * dx; \
- Y(new) = Y(in) + t * (Y(out) - Y(in)); \
- Z(new) = Z(in) + t * (Z(out) - Z(in)); \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*** Clip against -X side ***/
- #define OUTSIDE(K) (X(K) < -W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dx = X(out) - X(in); \
- dw = W(out) - W(in); \
- t = -(X(in) + W(in)) / (dw+dx); \
- X(new) = X(in) + t * dx; \
- Y(new) = Y(in) + t * (Y(out) - Y(in)); \
- Z(new) = Z(in) + t * (Z(out) - Z(in)); \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*** Clip against +Y side ***/
- #define OUTSIDE(K) (Y(K) > W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dy = Y(out) - Y(in); \
- dw = W(out) - W(in); \
- t = (Y(in) - W(in)) / (dw-dy); \
- X(new) = X(in) + t * (X(out) - X(in)); \
- Y(new) = Y(in) + t * dy; \
- Z(new) = Z(in) + t * (Z(out) - Z(in)); \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*** Clip against -Y side ***/
- #define OUTSIDE(K) (Y(K) < -W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dy = Y(out) - Y(in); \
- dw = W(out) - W(in); \
- t = -(Y(in) + W(in)) / (dw+dy); \
- X(new) = X(in) + t * (X(out) - X(in)); \
- Y(new) = Y(in) + t * dy; \
- Z(new) = Z(in) + t * (Z(out) - Z(in)); \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*** Clip against +Z side ***/
- #define OUTSIDE(K) (Z(K) > W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dz = Z(out) - Z(in); \
- dw = W(out) - W(in); \
- t = (Z(in) - W(in)) / (dw-dz); \
- X(new) = X(in) + t * (X(out) - X(in)); \
- Y(new) = Y(in) + t * (Y(out) - Y(in)); \
- Z(new) = Z(in) + t * dz; \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*** Clip against -Z side ***/
- #define OUTSIDE(K) (Z(K) < -W(K))
- #define COMPUTE_INTERSECTION( new, in, out ) \
- dz = Z(out) - Z(in); \
- dw = W(out) - W(in); \
- t = -(Z(in) + W(in)) / (dw+dz); \
- X(new) = X(in) + t * (X(out) - X(in)); \
- Y(new) = Y(in) + t * (Y(out) - Y(in)); \
- Z(new) = Z(in) + t * dz; \
- W(new) = W(in) + t * dw;
-
- GENERAL_CLIP
-
- #undef OUTSIDE
- #undef COMPUTE_INTERSECTION
-
- #undef GENERAL_CLIP
-
- *i = ii;
- *j = jj;
- return 1;
- }
-
-
-
-
- /*
- * Clip a polygon against the view volume defined by -w<=x,y,z<=w.
- * Input: n - number of vertices in input polygon.
- * vlist - list of indexes into VB.V* of polygon to clip.
- * Output: vlist - modified list of vertex indexes
- * Return: number of vertices in resulting polygon
- */
- GLuint gl_viewclip_polygon( GLuint n, GLuint vlist[] )
-
- {
- GLuint previ, prevj;
- GLuint curri, currj;
- GLuint vlist2[VB_MAX];
- GLuint n2;
- GLfloat dx, dy, dz, dw, t;
- GLuint incount, i;
-
- Space = CLIP_SPACE;
-
- /* Trivial inside clipping test. */
- incount = 0;
- for (i=0;i<n;i++) {
- GLuint j = vlist[i];
- GLfloat vi3 = VB.Clip[j][3];
- if (VB.Clip[j][0] <= vi3 && VB.Clip[j][0] >= -vi3 &&
- VB.Clip[j][1] <= vi3 && VB.Clip[j][1] >= -vi3 &&
- VB.Clip[j][2] <= vi3 && VB.Clip[j][2] >= -vi3) {
- incount++;
- }
- }
- if (incount==n) {
- return n;
- }
-
-
- /*
- * We use 6 instances of this code to implement clipping against the
- * 6 sides of the view volume. Prior to each we define the macros:
- * INLIST = array which lists input vertices
- * OUTLIST = array which lists output vertices
- * INCOUNT = variable which is the number of vertices in INLIST[]
- * OUTCOUNT = variable which is the number of vertices in OUTLIST[]
- * INSIDE(J) = test if vertex[J] is inside the view volume
- * COMPUTE_INTERSECTION(inv,outv,newv) = compute intersection of line
- * from inv[] to outv[] with the clipping plane and store
- * the result in newv[]
- */
-
- #define GENERAL_CLIP \
- if (INCOUNT<3) return 0; \
- previ = INCOUNT-1; /* let previous = last vertex */ \
- prevj = INLIST[previ]; \
- OUTCOUNT = 0; \
- for (curri=0;curri<INCOUNT;curri++) { \
- currj = INLIST[curri]; \
- if (INSIDE(currj)) { \
- if (INSIDE(prevj)) { \
- /* both verts are inside ==> copy current to outlist */ \
- OUTLIST[OUTCOUNT] = currj; \
- OUTCOUNT++; \
- } \
- else { \
- /* current is inside and previous is outside ==> clip */ \
- COMPUTE_INTERSECTION( VB.Clip[currj], VB.Clip[prevj], \
- VB.Clip[VB.Free] ) \
- /* interpolate aux info using the value of t */ \
- if (CC.ClipMask) interpolate_aux( VB.Free, t, currj, prevj ); \
- VB.Edgeflag[VB.Free] = VB.Edgeflag[prevj]; \
- OUTLIST[OUTCOUNT] = VB.Free; \
- VB.Free++; \
- if (VB.Free==VB_SIZE) VB.Free = 1; \
- OUTCOUNT++; \
- /* Output current */ \
- OUTLIST[OUTCOUNT] = currj; \
- OUTCOUNT++; \
- } \
- } \
- else { \
- if (INSIDE(prevj)) { \
- /* current is outside and previous is inside ==> clip */ \
- COMPUTE_INTERSECTION( VB.Clip[prevj], VB.Clip[currj], \
- VB.Clip[VB.Free] ) \
- /* interpolate aux info using the value of t */ \
- if (CC.ClipMask) interpolate_aux( VB.Free, t, prevj, currj ); \
- VB.Edgeflag[VB.Free] = VB.Edgeflag[prevj]; \
- OUTLIST[OUTCOUNT] = VB.Free; \
- VB.Free++; \
- if (VB.Free==VB_SIZE) VB.Free = 1; \
- OUTCOUNT++; \
- } \
- /* else both verts are outside ==> do nothing */ \
- } \
- /* let previous = current */ \
- previ = curri; \
- prevj = currj; \
- }
-
-
- /*
- * Clip against +X
- */
- #define INCOUNT n
- #define OUTCOUNT n2
- #define INLIST vlist
- #define OUTLIST vlist2
- #define INSIDE(J) ( VB.Clip[J][0] <= VB.Clip[J][3] )
-
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dx = outv[0] - inv[0]; \
- dw = outv[3] - inv[3]; \
- t = (inv[0]-inv[3]) / (dw-dx); \
- newv[0] = inv[0] + t * dx; \
- newv[1] = inv[1] + t * (outv[1]-inv[1]); \
- newv[2] = inv[2] + t * (outv[2]-inv[2]); \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef OUTCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*
- * Clip against -X
- */
- #define INCOUNT n2
- #define OUTCOUNT n
- #define INLIST vlist2
- #define OUTLIST vlist
- #define INSIDE(J) (VB.Clip[J][0] >= -VB.Clip[J][3])
-
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dx = outv[0]-inv[0]; \
- dw = outv[3]-inv[3]; \
- t = -(inv[0]+inv[3]) / (dw+dx); \
- newv[0] = inv[0] + t * dx; \
- newv[1] = inv[1] + t * (outv[1]-inv[1]); \
- newv[2] = inv[2] + t * (outv[2]-inv[2]); \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef OUTCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*
- * Clip against +Y
- */
- #define INCOUNT n
- #define OUTCOUNT n2
- #define INLIST vlist
- #define OUTLIST vlist2
- #define INSIDE(J) (VB.Clip[J][1] <= VB.Clip[J][3])
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dy = outv[1]-inv[1]; \
- dw = outv[3]-inv[3]; \
- t = (inv[1]-inv[3]) / (dw-dy); \
- newv[0] = inv[0] + t * (outv[0]-inv[0]); \
- newv[1] = inv[1] + t * dy; \
- newv[2] = inv[2] + t * (outv[2]-inv[2]); \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef OUTCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*
- * Clip against -Y
- */
- #define INCOUNT n2
- #define OUTCOUNT n
- #define INLIST vlist2
- #define OUTLIST vlist
- #define INSIDE(J) (VB.Clip[J][1] >= -VB.Clip[J][3])
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dy = outv[1]-inv[1]; \
- dw = outv[3]-inv[3]; \
- t = -(inv[1]+inv[3]) / (dw+dy); \
- newv[0] = inv[0] + t * (outv[0]-inv[0]); \
- newv[1] = inv[1] + t * dy; \
- newv[2] = inv[2] + t * (outv[2]-inv[2]); \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef OUTCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
-
-
- /*
- * Clip against +Z
- */
- #define INCOUNT n
- #define OUTCOUNT n2
- #define INLIST vlist
- #define OUTLIST vlist2
- #define INSIDE(J) (VB.Clip[J][2] <= VB.Clip[J][3])
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dz = outv[2]-inv[2]; \
- dw = outv[3]-inv[3]; \
- t = (inv[2]-inv[3]) / (dw-dz); \
- newv[0] = inv[0] + t * (outv[0]-inv[0]); \
- newv[1] = inv[1] + t * (outv[1]-inv[1]); \
- newv[2] = inv[2] + t * dz; \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef OUTCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
-
- /*
- * Clip against -Z
- */
- #define INCOUNT n2
- #define OUTCOUNT n
- #define INLIST vlist2
- #define OUTLIST vlist
- #define INSIDE(J) (VB.Clip[J][2] >= -VB.Clip[J][3])
- #define COMPUTE_INTERSECTION( inv, outv, newv ) \
- dz = outv[2]-inv[2]; \
- dw = outv[3]-inv[3]; \
- t = -(inv[2]+inv[3]) / (dw+dz); \
- newv[0] = inv[0] + t * (outv[0]-inv[0]); \
- newv[1] = inv[1] + t * (outv[1]-inv[1]); \
- newv[2] = inv[2] + t * dz; \
- newv[3] = inv[3] + t * dw;
-
- GENERAL_CLIP
-
- #undef INCOUNT
- #undef INLIST
- #undef OUTLIST
- #undef INSIDE
- #undef COMPUTE_INTERSECTION
-
- /* 'OUTCOUNT' clipped vertices are now back in v[] */
- return OUTCOUNT;
-
- #undef GENERAL_CLIP
- #undef OUTCOUNT
- }
-
-
-
-
- /**********************************************************************/
- /* Clipping against user-defined clipping planes. */
- /**********************************************************************/
-
-
-
- /*
- * If the dot product of the eye coordinates of a vertex with the
- * stored plane equation components is positive or zero, the vertex
- * is in with respect to that clipping plane, otherwise it is out.
- */
-
-
-
- /*
- * Clip a point against the user clipping planes.
- * Input: v - vertex-vector describing the point to clip.
- * Return: 0 = point was clipped
- * 1 = point not clipped
- */
- GLuint gl_userclip_point( const GLfloat v[] )
- {
- GLuint p;
-
- for (p=0;p<MAX_CLIP_PLANES;p++) {
- if (CC.Transform.ClipEnabled[p]) {
- GLfloat dot = v[0] * CC.Transform.ClipEquation[p][0]
- + v[1] * CC.Transform.ClipEquation[p][1]
- + v[2] * CC.Transform.ClipEquation[p][2]
- + v[3] * CC.Transform.ClipEquation[p][3];
- if (dot < 0.0F) {
- return 0;
- }
- }
- }
-
- return 1;
- }
-
-
- #define MAGIC_NUMBER -0.8e-03F
-
-
- /* Test if VB.Eye[J] is inside the clipping plane defined by A,B,C,D */
- #define INSIDE( J, A, B, C, D ) \
- ( (VB.Eye[J][0] * A + VB.Eye[J][1] * B \
- + VB.Eye[J][2] * C + VB.Eye[J][3] * D) >= MAGIC_NUMBER )
-
-
- /* Test if VB.Eye[J] is outside the clipping plane defined by A,B,C,D */
- #define OUTSIDE( J, A, B, C, D ) \
- ( (VB.Eye[J][0] * A + VB.Eye[J][1] * B \
- + VB.Eye[J][2] * C + VB.Eye[J][3] * D) < MAGIC_NUMBER )
-
-
- /*
- * Clip a line against the user clipping planes.
- * Input: i, j - indexes into VB.V*[] of endpoints
- * Output: i, j - indexes into VB.V*[] of (possibly clipped) endpoints
- * Return: 0 = line completely clipped
- * 1 = line is visible
- */
- GLuint gl_userclip_line( GLuint *i, GLuint *j )
- {
- GLuint p, ii, jj;
-
- Space = EYE_SPACE;
-
- ii = *i;
- jj = *j;
-
- for (p=0;p<MAX_CLIP_PLANES;p++) {
- if (CC.Transform.ClipEnabled[p]) {
- register GLfloat a, b, c, d;
- a = CC.Transform.ClipEquation[p][0];
- b = CC.Transform.ClipEquation[p][1];
- c = CC.Transform.ClipEquation[p][2];
- d = CC.Transform.ClipEquation[p][3];
-
- if (OUTSIDE( ii, a,b,c,d )) {
- if (OUTSIDE( jj, a,b,c,d )) {
- /* ii and jj outside ==> quit */
- return 0;
- }
- else {
- /* ii is outside, jj is inside ==> clip */
- GLfloat dx, dy, dz, dw, t, denom;
- dx = VB.Eye[ii][0] - VB.Eye[jj][0];
- dy = VB.Eye[ii][1] - VB.Eye[jj][1];
- dz = VB.Eye[ii][2] - VB.Eye[jj][2];
- dw = VB.Eye[ii][3] - VB.Eye[jj][3];
- denom = dx*a + dy*b + dz*c + dw*d;
- if (denom==0.0) {
- t = 0.0;
- }
- else {
- t = -(VB.Eye[jj][0]*a+VB.Eye[jj][1]*b
- +VB.Eye[jj][2]*c+VB.Eye[jj][3]*d) / denom;
- if (t>1.0F) t = 1.0F;
- }
- VB.Eye[VB.Free][0] = VB.Eye[jj][0] + t * dx;
- VB.Eye[VB.Free][1] = VB.Eye[jj][1] + t * dy;
- VB.Eye[VB.Free][2] = VB.Eye[jj][2] + t * dz;
- VB.Eye[VB.Free][3] = VB.Eye[jj][3] + t * dw;
-
- /* Interpolate colors, indexes, and/or texture coords */
- if (CC.ClipMask) interpolate_aux( VB.Free, t, jj, ii );
-
- ii = VB.Free;
- VB.Free++;
- if (VB.Free==VB_SIZE) VB.Free = 1;
- }
- }
- else {
- if (OUTSIDE( jj, a,b,c,d )) {
- /* ii is inside, jj is outside ==> clip */
- GLfloat dx, dy, dz, dw, t, denom;
- dx = VB.Eye[jj][0] - VB.Eye[ii][0];
- dy = VB.Eye[jj][1] - VB.Eye[ii][1];
- dz = VB.Eye[jj][2] - VB.Eye[ii][2];
- dw = VB.Eye[jj][3] - VB.Eye[ii][3];
- denom = dx*a + dy*b + dz*c + dw*d;
- if (denom==0.0) {
- t = 0.0;
- }
- else {
- t = -(VB.Eye[ii][0]*a+VB.Eye[ii][1]*b
- +VB.Eye[ii][2]*c+VB.Eye[ii][3]*d) / denom;
- if (t>1.0F) t = 1.0F;
- }
- VB.Eye[VB.Free][0] = VB.Eye[ii][0] + t * dx;
- VB.Eye[VB.Free][1] = VB.Eye[ii][1] + t * dy;
- VB.Eye[VB.Free][2] = VB.Eye[ii][2] + t * dz;
- VB.Eye[VB.Free][3] = VB.Eye[ii][3] + t * dw;
-
- /* Interpolate colors, indexes, and/or texture coords */
- if (CC.ClipMask) interpolate_aux( VB.Free, t, ii, jj );
-
- jj = VB.Free;
- VB.Free++;
- if (VB.Free==VB_SIZE) VB.Free = 1;
- }
- else {
- /* ii and jj inside ==> do nothing */
- }
- }
- }
- }
-
- *i = ii;
- *j = jj;
- return 1;
- }
-
-
-
-
- /*
- * Clip a polygon against the user clipping planes defined in eye coordinates.
- * Input: n - number of vertices.
- * vlist - list of vertices in input polygon.
- * Output: vlist - list of vertices in output polygon.
- * Return: number of vertices after clipping.
- */
- GLuint gl_userclip_polygon( GLuint n, GLuint vlist[] )
- {
- GLuint vlist2[VB_MAX];
- GLuint *inlist, *outlist;
- GLuint incount, outcount;
- GLuint curri, currj;
- GLuint previ, prevj;
- GLuint p;
-
- Space = EYE_SPACE;
-
- /* initialize input vertex list */
- incount = n;
- inlist = vlist;
- outlist = vlist2;
-
- for (p=0;p<MAX_CLIP_PLANES;p++) {
- if (CC.Transform.ClipEnabled[p]) {
- register float a = CC.Transform.ClipEquation[p][0];
- register float b = CC.Transform.ClipEquation[p][1];
- register float c = CC.Transform.ClipEquation[p][2];
- register float d = CC.Transform.ClipEquation[p][3];
-
- if (incount<3) return 0;
-
- /* initialize prev to be last in the input list */
- previ = incount - 1;
- prevj = inlist[previ];
-
- outcount = 0;
-
- for (curri=0;curri<incount;curri++) {
- currj = inlist[curri];
-
- if (INSIDE(currj, a,b,c,d)) {
- if (INSIDE(prevj, a,b,c,d)) {
- /* both verts are inside ==> copy current to outlist */
- outlist[outcount++] = currj;
- }
- else {
- /* current is inside and previous is outside ==> clip */
- GLfloat dx, dy, dz, dw, t, denom;
- /* compute t */
- dx = VB.Eye[prevj][0] - VB.Eye[currj][0];
- dy = VB.Eye[prevj][1] - VB.Eye[currj][1];
- dz = VB.Eye[prevj][2] - VB.Eye[currj][2];
- dw = VB.Eye[prevj][3] - VB.Eye[currj][3];
- denom = dx*a + dy*b + dz*c + dw*d;
- if (denom==0.0) {
- t = 0.0;
- }
- else {
- t = -(VB.Eye[currj][0]*a+VB.Eye[currj][1]*b
- +VB.Eye[currj][2]*c+VB.Eye[currj][3]*d) / denom;
- if (t>1.0F) {
- /*printf("t1=%g\n", t);*/
- t = 1.0F;
- }
- }
- /* interpolate new vertex position */
- VB.Eye[VB.Free][0] = VB.Eye[currj][0] + t*dx;
- VB.Eye[VB.Free][1] = VB.Eye[currj][1] + t*dy;
- VB.Eye[VB.Free][2] = VB.Eye[currj][2] + t*dz;
- VB.Eye[VB.Free][3] = VB.Eye[currj][3] + t*dw;
-
- /* interpolate color, index, and/or texture coord */
- if (CC.ClipMask) interpolate_aux( VB.Free, t, currj, prevj);
- VB.Edgeflag[VB.Free] = VB.Edgeflag[prevj];
-
- /* output new vertex */
- outlist[outcount++] = VB.Free;
- VB.Free++;
- if (VB.Free==VB_SIZE) VB.Free = 1;
- /* output current vertex */
- outlist[outcount++] = currj;
- }
- }
- else {
- if (INSIDE(prevj, a,b,c,d)) {
- /* current is outside and previous is inside ==> clip */
- GLfloat dx, dy, dz, dw, t, denom;
- /* compute t */
- dx = VB.Eye[currj][0]-VB.Eye[prevj][0];
- dy = VB.Eye[currj][1]-VB.Eye[prevj][1];
- dz = VB.Eye[currj][2]-VB.Eye[prevj][2];
- dw = VB.Eye[currj][3]-VB.Eye[prevj][3];
- denom = dx*a + dy*b + dz*c + dw*d;
- if (denom==0.0) {
- t = 0.0;
- }
- else {
- t = -(VB.Eye[prevj][0]*a+VB.Eye[prevj][1]*b
- +VB.Eye[prevj][2]*c+VB.Eye[prevj][3]*d) / denom;
- if (t>1.0F) {
- /*printf("t2=%g\n", t);*/
- t = 1.0F;
- }
- }
- /* interpolate new vertex position */
- VB.Eye[VB.Free][0] = VB.Eye[prevj][0] + t*dx;
- VB.Eye[VB.Free][1] = VB.Eye[prevj][1] + t*dy;
- VB.Eye[VB.Free][2] = VB.Eye[prevj][2] + t*dz;
- VB.Eye[VB.Free][3] = VB.Eye[prevj][3] + t*dw;
-
- /* interpolate color, index, and/or texture coord */
- if (CC.ClipMask) interpolate_aux( VB.Free, t, prevj, currj);
- VB.Edgeflag[VB.Free] = VB.Edgeflag[prevj];
-
- /* output new vertex */
- outlist[outcount++] = VB.Free;
- VB.Free++;
- if (VB.Free==VB_SIZE) VB.Free = 1;
- }
- /* else both verts are outside ==> do nothing */
- }
-
- previ = curri;
- prevj = currj;
-
- } /* for i */
-
- /* swap inv and outv pointers */
- {
- GLuint *tmp;
- tmp = inlist;
- inlist = outlist;
- outlist = tmp;
- incount = outcount;
- }
-
- } /* if */
- } /* for p */
-
- /* outlist points to the list of vertices resulting from the last */
- /* clipping. If outlist == vlist2 then we have to copy the vertices */
- /* back to vlist */
- if (outlist!=vlist2) {
- MEMCPY( vlist, vlist2, outcount * sizeof(GLuint) );
- }
-
- return outcount;
- }
-
-